package com.common.utils;

import io.minio.*;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.XmlParserException;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.rmi.ServerException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Component
@ConfigurationProperties(prefix = "file")
@Data
public class MinioUtil {
// https://blog.csdn.net/weixin_43148691/article/details/120344054

    private Logger logger = LoggerFactory.getLogger(MinioUtil.class);

    private String url;
    private String user;
    private String password;


    public MinioClient getClient() {
        try {

            return MinioClient.builder().endpoint(url).credentials(user, password).build();
        } catch (Exception e) {
            logger.info("minio链接异常  url: {}, user: {}, pwd: {},", url, user, password);
            throw new IllegalArgumentException("Minio 链接异常");
        }
    }

    /**
     * 创建桶
     */

    public void createBucket(String bucketName) {
//        getClient().removeBucket();


        try {
            MakeBucketArgs.Builder builder = MakeBucketArgs.builder();
            MakeBucketArgs build = builder.bucket(bucketName).build();

            getClient().makeBucket(build);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除桶
     */



    /**
     * 获取列表
     *
     * @param bucket
     * @param objectName
     * @return
     */
    public List<String> getObjectList(String bucket, String objectName) {
        ArrayList<String> nameList = new ArrayList<>();
        try {
            ListObjectsArgs.Builder builder = ListObjectsArgs.builder();

            builder.bucket(bucket);
//            builder.prefix(objectName);
            builder.recursive(true);

            ListObjectsArgs args = builder.build();

            Iterable<io.minio.Result<Item>> results = getClient().listObjects(args);


            for (Result<Item> result : results) {

                Item item = result.get();
//                if (item.isDir()) {
//                    //..
//                }
//                    item.size();
                nameList.add(item.objectName());

            }

        } catch (Exception e) {
            e.printStackTrace();
            logger.info("minio 获取列表失败 {}", (StringUtils.isEmpty(e.getMessage()) ? "未知异常请查看日志信息" : e.getMessage()));
        }
        return nameList;
    }

    /**
     * 获取桶列表
     *
     * @return
     */
    public List<Bucket> getBucketList() {
        try {
            return getClient().listBuckets();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("minio 未获取到所有桶");
            return null;
        }
    }

    /**
     * 判断文件(夹) 是否存在
     * 存在返回 true
     *
     * @param bucket
     * @param name
     * @return
     */
    public boolean existObject(String bucket, String name) {

        try {
            MinioClient client = getClient();
            StatObjectArgs.Builder builder = StatObjectArgs.builder();

            if (!StringUtils.isEmpty(name)) {
                builder.object(name);
            }
            StatObjectArgs args = builder.bucket(bucket).build();
            client.statObject(args);


        } catch (Exception e) {
            e.printStackTrace();
            logger.info(" {} 文件不存在", name);
            return false;
        }
        return true;
    }

    /**
     * 判断桶是否存在
     */
    public boolean existBucket(String bucket) {
        BucketExistsArgs.Builder builder = BucketExistsArgs.builder();
        builder.bucket(bucket);


        try {
            return getClient().bucketExists(builder.build());
        } catch (Exception e) {
            return false;
        }
    }


    /**
     * 删除文件夹
     */

    public void delDir() {
    }

    /**
     * 创建 dir
     *
     * @param bucket
     * @param rootDir
     * @param dir
     */
    public void createDir(String bucket, String rootDir, String dir) {
        try {
            if (StringUtils.isEmpty(bucket)) {
                throw new IllegalArgumentException("桶不能为空");
            }
            if (StringUtils.isEmpty(dir)) {
                throw new IllegalArgumentException("dir " + dir + " 为空");
            }
            if (!dir.endsWith("/")) {
                dir = dir + "/";
            }

            String fullDirPath = "";
            if (!StringUtils.isEmpty(rootDir)) {
                if (!existObject(bucket, rootDir)) {
                    throw new IllegalArgumentException("rootDir " + rootDir + " 不存在");
                }

                if (!StringUtils.isEmpty(rootDir)) {
                    if (rootDir.endsWith("/") && dir.startsWith("/")) {
                        fullDirPath = rootDir + dir.substring(1);
                    } else if (!rootDir.endsWith("/") && !dir.startsWith("/")) {
                        fullDirPath = rootDir + "/" + dir;
                    } else {
                        fullDirPath = rootDir + dir;
                    }
                }
            } else {
                fullDirPath = dir;
            }


            PutObjectArgs args = PutObjectArgs.builder().bucket(bucket).object(fullDirPath).stream(new ByteArrayInputStream(new byte[]{}), 0, -1).build();
            MinioClient client = getClient();
            client.putObject(args);

        } catch (Exception e) {
            e.printStackTrace();
            throw new IllegalArgumentException("minio 创建目录失败" + (StringUtils.isEmpty(e.getMessage()) ? "未知异常请查看日志信息" : e.getMessage()));
        }
    }

    /**
     * 获取文件流
     */
    public InputStream getObject(String bucketName, String objectName) {

        MinioClient client = getClient();

        GetObjectArgs.Builder builder = GetObjectArgs.builder();
        GetObjectArgs build = builder.bucket(bucketName).object(bucketName).build();
        try {
            return client.getObject(build);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
        MinioClient client = getClient();

        PutObjectArgs.Builder builder = PutObjectArgs.builder();

        PutObjectArgs build = builder.bucket(bucketName).object(objectName).stream(stream, stream.available(), PutObjectArgs.MIN_MULTIPART_SIZE).build();
        client.putObject(build);
    }

    /**
     * 上传文件
     * @param bucketName
     * @param objectName
     * @param file
     * @throws Exception
     */
    public void putObject(String bucketName, String objectName, MultipartFile file) throws Exception {
        getClient().putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(file.getInputStream(), file.getSize(), PutObjectArgs.MIN_MULTIPART_SIZE)
                        .contentType(file.getContentType())
                        .build());
    }

    public void cpObject(String bucketName, String sourceName, String targetName) {
        try {
            getClient().copyObject(CopyObjectArgs.builder()
                    .bucket(bucketName)
                    .object(targetName)
                    .source(CopySource.builder()
                            .bucket(bucketName)
                            .object(sourceName)
                            .build())
                    .build());
        } catch (ErrorResponseException e) {
            e.printStackTrace();
        } catch (InsufficientDataException e) {
            e.printStackTrace();
        } catch (InternalException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidResponseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 删除文件
     * @param bucket
     * @param objectName
     */
    public void delObject(String bucket, String objectName) {
        try {

//            List<String> objectList = getObjectList(bucket, objectName);
//            for (String s : objectList) {
                RemoveObjectArgs build = RemoveObjectArgs.builder()
                        .bucket(bucket)
                        .object(objectName)
                        .bypassGovernanceMode(true)
                        .build();
                getClient().removeObject(build);
//            }


        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            String replace = UUID.randomUUID().toString().replace("-", "");
            System.out.println(replace);
        }
    }

}
